package org.chipu.jnids.sancp;

import java.io.File;
import java.util.*;
import org.chipu.jnids.Jnids;
import org.chipu.jnids.beans.Flow;
import org.chipu.shared.util.singletons.DebugUtils;
import org.chipu.shared.util.singletons.Utils;
import org.junit.*;

public class SANCPReaderTester {
	private static List<Flow> connections;

	@BeforeClass
	public static void setUp() throws Exception {
		File testFile = new File(SANCPReaderTester.class.getResource("/org/chipu/jnids/sancp/stats.test").toURI());
		new Jnids();
		connections = NetFlowReader.load(Jnids.sancpConfFile).retrieveFlows(testFile, "stats");
		System.out.println(DebugUtils.getInMultipleLines(connections, "- "));
	}

	@Test
	public void getFirstFlow() {
		System.err.println("--- Last flow that should not be included");
		List<Flow> flows = new ArrayList<Flow>(connections);
		Collections.sort(flows, Flow.endTimeComparator);
		checkFirstFlow(1211667664, -1l, flows);
		checkFirstFlow(1212667657, -1l, flows);
		checkFirstFlow(1212667661, 1212667656000l, flows);
		checkFirstFlow(1212667671, 1212667658000l, flows);
		checkFirstFlow(1212667764, 1212667668000l, flows);
		checkFirstFlow(1212671689, 1212669105000l, flows);
		checkFirstFlow(1213667664, 1212671689000l, flows);
	}

	@Test
	public void getLastFlow() {
		System.err.println("--- Last flow that should be included");
		List<Flow> flows = new ArrayList<Flow>(connections);
		Collections.sort(flows, Flow.startTimeComparator);
		checkLastFlow(1211667664, -1l, flows);
		checkLastFlow(1212667656, 1212667656000l, flows);
		checkLastFlow(1212667657, 1212667656000l, flows);
		checkLastFlow(1212667671, 1212667668000l, flows);
		checkLastFlow(1212667764, 1212667668000l, flows);
		checkLastFlow(1213667664, 1212671689000l, flows);
	}

	private void checkFirstFlow(int timeInSeconds, long lastFlowExpected, List<Flow> flows) {
		int flowIndex = ProfileCreatorFiles.getFirstFlowIndex(timeInSeconds, flows);
		if (flowIndex == -1) {
			// System.err.println("Index=-\t\tTime: " + timeInSeconds + " " + Utils.toDate(timeInSeconds)
			// + "\t\tActual: -\tExpected: " + getExpectedDate(lastFlowExpected));
			Assert.assertEquals("Expected start: " + getExpectedDate(lastFlowExpected) + ". Actual start: -", lastFlowExpected,
				-1);
			return;
		}
		int flowTime = flows.get(flowIndex).startTimeInSeconds;
		Date d = Utils.toDate(flowTime);
		// System.err.println("Index=" + flowIndex + "\t\tTime: " + timeInSeconds + " "
		// + Utils.toDate(timeInSeconds) + "\t\tActual: " + flowTime + "   " + d + "\tExpected: "
		// + getExpectedDate(lastFlowExpected));
		Assert.assertEquals("Expected start: " + getExpectedDate(lastFlowExpected) + ". Actual start: " + d, lastFlowExpected,
			d.getTime());
	}

	private String getExpectedDate(long time) {
		return time == -1? "-": new Date(time).toString();
	}

	private void checkLastFlow(int timeInSeconds, long lastFlowExpected, List<Flow> flows) {
		int flowIndex = ProfileCreatorFiles.getLastFlowIndex(timeInSeconds, flows);
		if (flowIndex == -1) {
			// System.err.println("Index=-\t\tTime: " + timeInSeconds + " " + Utils.toDate(timeInSeconds)
			// + "\t\tActual: -\tExpected: " + getExpectedDate(lastFlowExpected));
			Assert.assertEquals("Expected start: " + getExpectedDate(lastFlowExpected) + ". Actual start: -", lastFlowExpected,
				-1);
			return;
		}
		int flowTime = flows.get(flowIndex).startTimeInSeconds;
		Date d = Utils.toDate(flowTime);
		// System.err.println("Index=" + flowIndex + "\t\tTime: " + timeInSeconds + " "
		// + Utils.toDate(timeInSeconds) + "\t\tActual: " + flowTime + "   " + d + "\tExpected: "
		// + getExpectedDate(lastFlowExpected));
		Assert.assertEquals("Expected start: " + getExpectedDate(lastFlowExpected) + ". Actual start: " + d, lastFlowExpected,
			d.getTime());
	}

	// @Test
	// public void getConnectionsAt() {
	// System.out.println("Getting connections at " + new Date(1206460140500l) + " from list:");
	// System.out.println(DebugUtils.getInMultipleLines(connections, "\t"));
	//
	// ArrayList<Flow> c1 = new ArrayList<Flow>(connections);
	// ArrayList<Flow> c2 = new ArrayList<Flow>(connections);
	// Collections.sort(c1, new Comparator<Flow>() {
	// @Override
	// public int compare(Flow o1, Flow o2) {
	// return o1.startTimeInSeconds - o2.startTimeInSeconds;
	// }
	// });
	// Collections.sort(c2, new Comparator<Flow>() {
	// @Override
	// public int compare(Flow o1, Flow o2) {
	// return o1.stopTimeInSeconds - o2.stopTimeInSeconds;
	// }
	// });
	// Set<Flow> connectionsIn = new HashSet<Flow>();
	// Set<Flow> connectionsOut = new HashSet<Flow>();
	// ProfileCreator.loadConnectionsAt(1206460140, c1, c2, connectionsIn, connectionsOut);
	//
	// System.out.println("Connections in:");
	// System.out.println(DebugUtils.getInMultipleLines(connectionsIn, "\t"));
	// System.out.println("Connections out:");
	// System.out.println(DebugUtils.getInMultipleLines(connectionsOut, "\t"));
	// }
}